#!/usr/bin/env python
# coding: utf-8
#
# short url service

import sys

import os
import uuid
import urllib
import urlparse
import threading
import bottle
import defer
from bottle import route, request#, redirect

from utils import *
import optparse

url_prefix = "http://goto.baidu.com/"
mu = threading.RLock() 

__dir__ = os.path.dirname(os.path.abspath(__file__))

@route("/")
def add():
	return bottle.static_file('add.html', root = os.path.join(__dir__, 'static/'))

@route("/api/add", method="post")
def do_add():
    d = defer.Deferred()
    mu.acquire(1)
    d.add_callback(mu.release)
    url = request.forms.get('url')
    alias = request.forms.get('alias', '')
    ret = { "status": 0, "tinyurl": url_prefix + alias, }
    if alias:
        val = urlGet(alias)
        if val:
            return {"status": 1, "status_txt": "alias already exists, old value is " + val}
            bottle.abort(403, "alias already existed, value = " + val)
    else: # generate alias
        while True:
            if alias and not urlGet(alias):
                break
            alias = str(uuid.uuid1())[0:4]
    urlSet(alias, url)
    ret["tinyurl"] = url_prefix + alias
    return ret

@route('/info/<short>')
def info(short):
    clicks = infoGet(short)
    return {
        "tinyurl": short,
        "longurl": urlGet(short),
        "clicks": clicks,
    }

@route('/<short>')
def redirect(short):
    d = defer.Deferred()
    mu.acquire(0)
    d.add_callback(mu.release)

    shortUrl, specPort = splitHost(short)
    fullUrl = urlGet(shortUrl)
    if not fullUrl:
        bottle.abort(404, "Not found")
    else:
        infoUpdate(shortUrl)
        parts = list(urlparse.urlsplit(fullUrl))
        netloc = parts[1]
        host, port = splitHost(netloc)
        if specPort:
            port = specPort
        parts[1] = joinHost(host, port)
        bottle.redirect(urlparse.urlunsplit(parts))

@route('/static/<filename:path>')
def send_static(filename):
    return bottle.static_file(filename, root=os.path.join(__dir__, 'static'))

if __name__ == '__main__':
    parser = optparse.OptionParser()
    parser.add_option('-H', '--host', dest="host", default="0.0.0.0",
        help="host to listen", type="string", action="store")
    parser.add_option('-p', '--port', dest="port", default=8080,
        help="port to listen", type="int", action="store")
    parser.add_option('-d', '--debug', dest="debug", default=True,
        help="open debug info", action="store_true")
    opts, args = parser.parse_args()

    bottle.run(host = opts.host, port = opts.port, debug = opts.debug)
